﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using UserDefinedForms.Entities;
using UDFDesign.GUIComponent.CustomControl;
using UserDefinedForms.Business;

namespace UDFDesign.GUIComponent.CustomControl
{
    public enum MoveMode
    {
        NotMoving,
        Form,
        ResizeBoth
    }

    public enum ControlTypes
    {
        Base,
        TextBox,
        NumberTextBox,
        DateTimePicker,
        CheckBox,
        RadioButton,
        ComboBox,
        AutoCalculate

    }

    public class DesignableControl : Control
    {
        #region member

        private static ControlListItemService listItemService = new ControlListItemService();

        protected Point? m_clickLoc = null;
        protected MoveMode m_moveMode = MoveMode.NotMoving;
        protected Size m_minimumSize;
        protected Control selfControl = null;
        protected ToolTip toolTip = new ToolTip();

        #endregion

        #region property

        protected FormControl controlORM = null;

        public FormControl ControlORM
        {
            get { return controlORM; }
        }

        protected SupFormControlMappingObjectcs controlMappingObj= null;

        public SupFormControlMappingObjectcs ControlMappingObj
        {
          get { return controlMappingObj; }
        }


        protected PropertiesPanel propPanel;

        public PropertiesPanel PropPanel
        {
            get { return propPanel; }
            set { propPanel = value; }
        }

        protected Boolean isSelected = false;

        public Boolean IsSelected
        {
            get { return isSelected; }
            set { isSelected = value; }
        }

        public Control SelfControl
        {
            get { return selfControl; }
            set { selfControl = value; }
        }
        protected DrawingBoard drawingBoard;

        public DrawingBoard DrawingBoard
        {
            get { return drawingBoard; }
            set { drawingBoard = value; }
        }

        public new Size Size
        {
            set
            {
                selfControl.Size = value;

                base.Size = selfControl.Size;
            }
            get
            {
                return base.Size;
            }
        }

        

        [Category("Behavior"), DefaultValue(true)]
        public bool Movable { get; set; }
        /*
        [Browsable(false)]
        public Rectangle TitleBarRectangle
        {
            get { return new Rectangle(this.ClientRectangle.X, this.ClientRectangle.Y, this.ClientRectangle.Width, (int)(this.Font.Height * 1.25)); }
        }
        */
        [Browsable(false)]
        public Rectangle ResizeHandleRectangle
        {
            get { return new Rectangle(this.ClientRectangle.Width - 15, this.ClientRectangle.Height - 15, 15, 15); }
        }
/*
        public virtual String Name
        {
            get
            {
                return base.Name;
            }
            set
            {
                controlORM.Name = value;
                base.Name = value;
            }

        }
        */
        public virtual ControlTypes ControlType
        {
            get
            {
                return ControlTypes.Base;
            }
        }

        public virtual String ToolTipText
        {
            get
            {
                return controlMappingObj.ToolTipText;
            }
            set
            {
                this.toolTip.SetToolTip(this, value);
            }
        }


        protected List<string> listValue = new List<string>();
        public virtual List<string> List
        {
            get
            {
                return listValue;
            }
            set
            {
                // do nothing
            }
        }

        #endregion

        #region constructor
        public DesignableControl()
        {
            this.controlORM = new FormControl();

            controlMappingObj = new SupFormControlMappingObjectcs();
            controlMappingObj.setControl(this);
            this.Movable = true;
            initControl();

        }

        public DesignableControl(FormControl entity)
        {
            initControl();
            this.controlORM = entity;

            TypeConverter tc = TypeDescriptor.GetConverter(typeof(Font));
            this.Font = (Font)tc.ConvertFromString(entity.Font);

            this.Size = new Size((int)entity.Width, (int)entity.Height);
            this.Location = new Point((int)entity.Left, (int)entity.Top);

            TList<ControlListItem> listItemEntities = listItemService.GetByControlId(entity.ControlId);
            this.List = new List<string>();
            for (int i = 0; i < listItemEntities.Count; i++)
            {
                this.List[i] = listItemEntities[i].ItemData;
            }


            controlMappingObj = new SupFormControlMappingObjectcs();
            controlMappingObj.setControl(this);
            this.Movable = true;
            

        }

        
        #endregion

        #region method

        public FormControl toORM()
        {
            controlMappingObj.updateInfo();
            controlORM.Name = controlMappingObj.Name;
            controlORM.ControlTypeId = (int)this.ControlType;
            controlORM.ToolTipText = controlMappingObj.ToolTipText;
            controlORM.Border = controlMappingObj.Border;
            controlORM.Left = controlMappingObj.Location.X;
            controlORM.Top = controlMappingObj.Location.Y;
            controlORM.Width = controlMappingObj.Size.Width;
            controlORM.Height = controlMappingObj.Size.Height;
            TypeConverter tc = TypeDescriptor.GetConverter(typeof(Font));
            controlORM.Font = tc.ConvertToString(controlMappingObj.Font);
            controlORM.DefaultValue = controlMappingObj.DefaultValue;
            controlORM.Visible = controlMappingObj.Visible;
            controlORM.Enable = controlMappingObj.Enable;
            controlORM.IsSummaryField = false;
            controlORM.IsCommon = false;
            controlORM.IsCode = false;
            controlORM.IsLayout = false;
            controlORM.Status = controlMappingObj.Status;
            controlORM.Description = controlMappingObj.Description;
            return controlORM;
        }

        protected virtual void initControl()
        {
        }
        /*
        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;

            // Draw Background
            g.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle);

            // Draw Titlebar
          //  g.FillRectangle(new SolidBrush(this.TitleBarColor), this.ClientRectangle);
         //   g.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), new Point(this.ClientRectangle.X + (int)(this.ClientRectangle.Width / 2 - g.MeasureString(this.Text, this.Font).Width / 2), this.ClientRectangle.Y + this.TitleBarRectangle.Height / 2 - this.Font.Height / 2));

            base.OnPaint(e);

            // Draw Resize Anchor if it can be used
            if (this.Movable)
            {
                g.DrawLine(Pens.Black, this.ResizeHandleRectangle.Right - 3, this.ResizeHandleRectangle.Top + 3, this.ResizeHandleRectangle.Left + 3, this.ResizeHandleRectangle.Bottom - 3);
                g.DrawLine(Pens.Black, this.ResizeHandleRectangle.Right - 3, this.ResizeHandleRectangle.Top + 6, this.ResizeHandleRectangle.Left + 6, this.ResizeHandleRectangle.Bottom - 3);
                g.DrawLine(Pens.Black, this.ResizeHandleRectangle.Right - 3, this.ResizeHandleRectangle.Top + 9, this.ResizeHandleRectangle.Left + 9, this.ResizeHandleRectangle.Bottom - 3);
            }

            // Draw Border
            g.DrawRectangle(Pens.Black, this.ClientRectangle.X, this.ClientRectangle.Y, this.ClientRectangle.Width - 1, this.ClientRectangle.Height - 1);
           // g.DrawLine(Pens.Black, new Point(this.ClientRectangle.X, this.TitleBarRectangle.Bottom), new Point(this.TitleBarRectangle.Right, this.TitleBarRectangle.Bottom));
        }
        */

        public void delete()
        {
            if (drawingBoard != null)
            {
                drawingBoard.deleteControl(this);
            }
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            this.select();
            base.OnMouseClick(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            
            if (drawingBoard == null) return;
            // We only want stuff to happen if we say it can.
            if (this.Movable)
            {
                if (e.Button == MouseButtons.Left)
                {
                    // Figure out what we're doing... if it's something, we want to store the last click location.
                    if (m_clickLoc == null)
                    {
                        if (this.ClientRectangle.Contains(e.Location) && !ResizeHandleRectangle.Contains(e.Location))
                            m_moveMode = MoveMode.Form;
                        else
                            m_moveMode = MoveMode.NotMoving;

                        if (m_moveMode != MoveMode.NotMoving)
                            m_clickLoc = new Point(e.X, e.Y);
                    }

                    // If we're not, not moving, figure out what we should be doing! (oooh poetry)
                    if (m_moveMode != MoveMode.NotMoving)
                    {
                        switch (m_moveMode)
                        {
                            case MoveMode.Form:
                                // Just moving, update the form's location
                                Point newWestNorthPoint = new Point(this.Location.X + e.X - m_clickLoc.Value.X, this.Location.Y + e.Y - m_clickLoc.Value.Y);
                                Point newEastSouthPoint = new Point(newWestNorthPoint.X + this.Size.Width, newWestNorthPoint.Y + this.Size.Height);
                                if (this.Parent.ClientRectangle.Contains(newWestNorthPoint) && this.Parent.ClientRectangle.Contains(newEastSouthPoint))
                                {
                                    this.Location = newWestNorthPoint;
                                }
                                break;
                        }
                    }

                    if (m_clickLoc == null)
                    {
                        if (this.ClientRectangle.Contains(e.Location) && !ResizeHandleRectangle.Contains(e.Location))
                            m_moveMode = MoveMode.Form;
                        else if (this.ResizeHandleRectangle.Contains(e.Location))

                            m_moveMode = MoveMode.ResizeBoth;
                        else
                            m_moveMode = MoveMode.NotMoving;

                        if (m_moveMode != MoveMode.NotMoving)
                            m_clickLoc = new Point(e.X, e.Y);


                    }



                    switch (m_moveMode)
                    {

                        case MoveMode.ResizeBoth:
                            Size newSize = new Size(this.Size.Width + e.X - m_clickLoc.Value.X, this.Size.Height + e.Y - m_clickLoc.Value.Y);
                            bool needsRedraw = false;

                            // Handle width and heigh resizing separately so that when we hit the minimum size for one, we can still resize the other.
                            // Also, only allow sizing if the particular dimension of the new size is greater than the corresponding minimum.
                            // Finally, if we do a resize, we need to force a redraw and update the click location so we always resize based on a delta movement.

                            Point newEastSouthPoint = new Point(this.Location.X + newSize.Width, this.Location.Y + newSize.Height);
                            if (this.Parent.ClientRectangle.Contains(newEastSouthPoint))
                            {
                                /*
                                control.Size = new Size(newSize.Width,newSize.Height);

                                this.Size = new Size(control.Size.Width,control.Size.Height);
                                m_clickLoc = new Point(m_clickLoc.Value.X, m_clickLoc.Value.Y);
                                needsRedraw = true;
                                 */

                                if (newSize.Width > m_minimumSize.Width)
                                {
                                    selfControl.Size = new Size(newSize.Width, this.Size.Height);
                                    this.Size = new Size(selfControl.Width, selfControl.Height);
                                    m_clickLoc = new Point(e.X, m_clickLoc.Value.Y);
                                    needsRedraw = true;
                                }

                                if (newSize.Height > m_minimumSize.Height)
                                {
                                    selfControl.Size = new Size(this.Size.Width, newSize.Height);
                                    this.Size = new Size(selfControl.Width, selfControl.Height);
                                    m_clickLoc = new Point(m_clickLoc.Value.X, e.Y);
                                    needsRedraw = true;
                                }

                            }
                            if (needsRedraw)
                                this.Invalidate();

                            break;
                    }


                }
                else
                {


                    // No desired button pressed lets clear all our states
                    m_moveMode = MoveMode.NotMoving;
                    m_clickLoc = null;

                    if (this.ClientRectangle.Contains(e.Location) && !ResizeHandleRectangle.Contains(e.Location))
                        this.Cursor = Cursors.SizeAll;
                    else if (this.ResizeHandleRectangle.Contains(e.Location))

                        this.Cursor = Cursors.SizeNWSE;
                    else
                        this.Cursor = Cursors.Default;
                }



                controlMappingObj.updateInfo();
            }
            
            base.OnMouseMove(e);
        }


        public void select()
        {
            if (DrawingBoard != null)
            {
                controlMappingObj.updateInfo();
                DrawingBoard.selectControl(this);
            }
        }

        public void save()
        {
        }

        #endregion

    }
}

